from core import nmt
#from untils import sqlclass as sql
import tensorflow as tf
from flask import Flask, session, request, render_template, current_app, send_file, send_from_directory, make_response, flash
from untils.lock import Lock
import datetime
import os
import pickle as pkl
from untils import tools
from untils import fileprocess


batch_size = 128
num_epochs = 50
lr = 1e-3
optimizer = 'adam'
dropout = 0.2
src_max_vocab_size = 100000   #6改到10
tgt_max_vocab_size = 8800
embedding_size = 128
hidden_size = 256
src_max_seq_len = 40
tgt_max_seq_len = 40
tgt_start_id = 2  # <S>
tgt_end_id = 0  # <PAD>
max_gradient_norm = 1.
maximum_iterations = 40
cf = tf.compat.v1.ConfigProto(allow_soft_placement=True, log_device_placement=False)
cf.gpu_options.allow_growth = True
def get_dict_model_session():
    with open('../core/data/preprocess/vocab_dict.pkl', 'rb') as fr:
        en_word2id, en_id2word, ch_word2id, ch_id2word = pkl.load(fr)
    sess = tf.compat.v1.Session(config=cf)
    with tf.device('/cpu:0'):
        model = nmt.NMTModel(src_max_vocab_size=src_max_vocab_size,
                             tgt_max_vocab_size=tgt_max_vocab_size,
                             embedding_size=embedding_size,
                             hidden_size=hidden_size,
                             src_max_seq_len=src_max_seq_len,
                             tgt_max_seq_len=tgt_max_seq_len,
                             tgt_start_id=tgt_start_id,
                             tgt_end_id=tgt_end_id,
                             max_gradient_norm=max_gradient_norm,
                             maximum_iterations=maximum_iterations,
                             optimizer=optimizer)
        saver = tf.train.Saver()
        saver.restore(sess, tf.train.latest_checkpoint('../core/model'))
        return model, sess, en_word2id, en_id2word, ch_word2id, ch_id2word
# --- 线上服务 ---
import config
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.lock=Lock.get_file_lock()
app.config.from_object(config)
# db = SQLAlchemy(app, use_native_unicode='utf8')
from untils.sqlclass import db, user, file
db.init_app(app)
# db.create_all(app=app)
# exit(0)
#@app.route('/index', methods=['GET', 'POST'])
# def online_predict():
#     if request.method == "POST":
#         try:
#             x = request.form['eng']
#             X = nmt.segment(x, jieba.cut)
#             X = nmt.transform(X, en_word2id)
#             X = nmt.padding(X, src_max_seq_len)
#             X_len = np.sum((X > 0), axis=1)
#             translations = sess.run(model.translations,
#                                     feed_dict={model.X: X,
#                                                model.Y_out: [[]],
#                                                model.Y_in: [[]],
#                                                model.X_len: X_len,
#                                                model.Y_in_len: [],
#                                                model.Y_out_len: [],
#                                                model.lr: lr,
#                                                model.dropout: 0.})
#             translations = nmt.transform2word(translations, ch_id2word)
#             return render_template('index.html', ENG=x, RESULT=translations[0].replace("<PAD>", ""))
#         except Exception as e:
#             return jsonify(errcode='error', error=str(e))
#     return render_template('index.html')
from flask import redirect
model, sess, en_word2id, en_id2word, ch_word2id, ch_id2word = 1, 2, 3, 4, 5, 6
@app.route('/', methods=['get'])
def index2f():
    session.clear()
    return redirect('/index')

#起始页
@app.route('/index', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # 尝试上传时将临时文件写ru用户uid目录之下
        # session有无用户身份
        #没有就返回错
        userid = session.get('user_id')
        if not userid or userid=='1':
            flash("账户状态异常请重新登录")
            return 0
        u = user.query.filter(user.user_id==userid).first()
        if u.user_fileavl==0:
            flash("文件上传次数已用完")
            return '2'
        abpath = os.path.abspath('../upload/'+str(userid)+'/')
        for upload in request.files.getlist("file"):
            filename = upload.filename.rsplit("/")[0]
            destination = "/".join([abpath, filename])
            if os.path.exists(destination):
                os.remove(destination)
                f = file.query.filter(file.file_name==filename, file.user_id==userid).first()
                db.session.delete(f)
            upload.save(destination)
            u.user_fileavl=u.user_fileavl-1
            new_file = file(file_name=filename,file_uptime=datetime.datetime.now(), file_done=False, file_slen=os.path.getsize(destination),\
                            file_dlen=0, file_path=destination, file_format=filename.rsplit('.')[-1], user_id=userid)
            db.session.add(new_file)
            try:
                db.session.commit()
            except Exception as e:
                print(e)
                flash("上传异常")
                db.session.rollback()
                return '0'
        #return jsonify("上传成功！")
        return "1"
    else:
        if session.get('user_id') and not session.get('user_id')=="1":
            u = user.query.filter(user.user_id==session.get('user_id')).first()
            flash("登陆成功！")
            return render_template('html.html', user=u)
        return render_template('html.html', user=1)

#获取文件列表
@app.route('/filepage/<userid>', methods=['get', 'post'])
def filepage(userid):
    t = 1
    file_list = []
    uid = str(userid)
    if uid != str(session.get('user_id')):
        flash("账户状态异常，重新登陆")
        return '0'
    upfilelist, downfilelist = [], []
    if os.path.exists("../upload/" + uid):
        upfilelist = os.listdir("../upload/" + uid + "/")
    else:
        os.mkdir("../upload/" + uid + "/")
    if os.path.exists("../output/" + uid):
        downfilelist = os.listdir("../output/" + uid + "/")
    else:
        os.mkdir("../output/" + uid + "/")
    realfilelist = file.query.filter(file.user_id==userid).all()
    u = user.query.filter(user.user_id==uid).first()
    return render_template('userfilelist.html', files=list(enumerate(realfilelist)), user=u)

#翻译进程
def translate(lock, user_idt, filenam):
    lock.acquire()
    f = file.query.filter(file.user_id==user_idt, file.file_name==filenam).first()
    if f.file_state==True:
        raise IOError
    f.file_state=True
    db.session.commit()
    lock.release()
    #操作翻译 xie log
    re = fileprocess.parserfile(filenam, user_idt)
    if re==0:
        lock.acquire()
        f.file_state = False
        f.file_done = False
        db.session.commit()
        lock.release()
        raise IOError
    #xie log
    # f = file.query.filter_by(file.user_id = user_id, file.filename = filename).first()
    f = file.query.filter(file.user_id == user_idt, file.file_name == filenam).first()
    lock.acquire()
    f.file_state=False
    f.file_done=True
    db.session.commit()
    lock.release()
from multiprocessing import Process
#去翻译文件
@app.route("/translate/<file_id>",methods=['post'])
def funcfile(file_id):
    fileid, uid = file_id.split('_', 2)
    filename = file.query.filter(file.file_id==fileid).first().file_name
    if not session.get('user_id') or uid != session.get('user_id'):
        flash("当前帐号状态异常！")
        return '0'
#开启进程  modify file_done
    try:
        translate(current_app.lock, uid, filename)
        return '1'
    except Exception as e:
        print(e)
        return '0'

@app.route('/delete/<file_id>', methods=['post'])
def delfile(file_id):
    user_id = session.get('user_id')
    if not user_id:
        flash('帐号状态异常！')
        return '0'
    else:
        f = file.query.filter(file.file_id==file_id).first()
        db.session.delete(f)
        try:
            db.session.commit()
        except:
            flash("删除失败！")
            db.session.rollback()
            return '0'
        return '1'
#下载译后文件
@app.route('/downdfile/<fileid>')  # filename采用userid_filename
def downdfile(fileid):
    uid, fileid = fileid.split('_')
    f = file.query.filter(file.file_id == fileid).first()
    filename = f.file_name
    if not session.get('user_id') or uid != session.get('user_id'):
        flash("当前帐号状态异常！")
        return '0'
    directory = os.path.abspath('../output/' + str(uid) + '/')
    response = make_response(send_from_directory(directory, filename, as_attachment=True))
    response.headers["Content-Disposition"] = "attachment; filename={}".format(filename.encode().decode('latin-1'))
    return response

@app.route('/verifycode',methods=['post'])
def verifycode():
    code = request.form.get('code')
    if code == session['code']:
        return '1'
    else:
        return '0'
#获取验证码图片
@app.route("/userid")
def sureuid():
    code, buf_str = tools.generatecode()
    session['code'] = code
    return buf_str

@app.route('/loginout')
def loginout():
    session.clear()
    return redirect('/')
#登录验证
@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        id = request.form.get('id')
        pwd = request.form.get('pwd')
        u = user.query.filter(user.user_id==id).first()
        if not u:
            return '0'
        if pwd == u.user_pwd:
            u.funct(session)
            return '1'
            #return render_template('html.html', user=u)
        else:
            return '0'
    else:
        return render_template('login.html')

#注册页面
@app.route('/register', methods=['get', 'post'])
def register():
    if request.method == 'POST':
        id = request.form.get('user_id')
        if user.query.filter(user.user_id == id).first():
            flash("该账户短时间内已经使用！")
            return '0'
        name=request.form.get('user_name')
        pwd=request.form.get('pwd-hash')
        phone = request.form.get('mobile')
        times = datetime.datetime.now()
        ip = request.remote_addr
        fileavl =3
        mail = request.form.get('email')
        u = user(user_id=id, user_name=name, user_fileavl=fileavl, user_pwd=pwd, user_phone=phone, user_mail=mail, login_time=times, local_ip=str(ip))
        db.session.add(u)
        try:
            db.session.commit()
        except:
            db.session.rollback()
            flash("注册写入时失败！请重新注册")
            return '0'
        return '1'
    else:
        return render_template('register.html')

#下载源文件
@app.route('/downsfile/<fileid>',methods=['post','get'])  # filename采用userid_filename
def downsfile(fileid):
    uid, fileid = fileid.split('_')
    f = file.query.filter(file.file_id==fileid).first()
    filename = f.file_name
    if not session.get('user_id') or uid != session.get('user_id'):
        flash("当前帐号状态异常！")
        return '0'
    directory = os.path.abspath('../upload/' + str(uid) + '/')
    response = make_response(send_from_directory(directory, filename, as_attachment=True))
    response.headers["Content-Disposition"] = "attachment; filename={}".format(filename.encode().decode('latin-1'))
    return response

#验证uid是否可用
@app.route('/sureid', methods=['post'])
def ensureid():
    id = str(request.form.get('user_id'))
    id = id.strip()
    #id in db
    if user.query.filter(user.user_id==id).first:
        return '1'
    else:
        return '0'

@app.route('/lttranslate',methods=['post','get'])
def rawtrans():
    from core import nmt
    text=request.form.get('text')
    result =""
    if not session.get('user_id'):#自研翻译器
        try:
            result=nmt.predict(text)#model,sess,en_word2id,en_id2word,ch_word2id,ch_id2word,
        except Exception as e:
            print(e)
            result=fileprocess.opredict(text,0)
    else:
        result = fileprocess.opredict(text,0)

    return result

if __name__ == "__main__":
    # model, sess, en_word2id, en_id2word, ch_word2id, ch_id2word = get_dict_model_session()
    # g.parameter=[model, sess, en_word2id, en_id2word, ch_word2id, ch_id2word]
    app.run('0.0.0.0', port=8899, debug=True, threaded=True)
